package com.sugon.modules.mold.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import com.sugon.dao.*;
import com.sugon.entity.*;
import com.sugon.modules.base.consts.SysApproveStatusConst;
import com.sugon.modules.base.model.dto.HandleApproveResult;
import com.sugon.modules.base.service.impl.AbstractErmsBaseApproveManager;
import com.sugon.modules.device.consts.DevRepairTicketStage;
import com.sugon.modules.device.model.vo.DevRepairExceptionParam;
import com.sugon.modules.mold.consts.MoldPmTicketProgressConst;
import com.sugon.modules.mold.consts.MoldReplacePartProgress;
import com.sugon.modules.mold.consts.MoldStatusChangeAction;
import com.sugon.modules.mold.model.dto.MoldYearlyFaultStatDTO;
import com.sugon.modules.mold.model.vo.BaseRepairRecordParamVO;
import com.sugon.modules.mold.service.IMoldArchivesManager;
import com.sugon.modules.mold.service.IMoldRepairRecordManager;
import com.sugon.modules.sys.consts.ProcessProgressStatus;
import com.sugon.modules.sys.consts.SysUserConst;
import com.sugon.service.*;
import com.sugon.utils.PageUtils;
import com.sugon.utils.ProcessInfoEnum;
import com.sugon.utils.Query;
import org.apache.shiro.util.Assert;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author ： YuXD
 * @description： 模具紧急维护业务Service实现类
 * @date ： 2020-08-04 下午 8:04
 * @version: 1.0
 */
@Service
public class MoldRepairRecordManagerImpl extends AbstractErmsBaseApproveManager implements IMoldRepairRecordManager {

    @Resource
    private ModuleRepairRocordService moldRepairRecordService;
    @Resource
    private SysProcessInfoService sysProcessInfoService;
    @Resource
    private ModuleArchivesDao moduleArchivesDao;
    @Resource
    private DevMaintenRepairService devMaintenRepairService;
    @Resource
    private DevMaintenRepairDao devMaintenRepairDao;
    @Resource
    private ModuleArchivesService moduleArchivesService;
    @Resource
    private ModuleRepairRocordDao moduleRepairRocordDao;
    @Resource
    private IMoldArchivesManager moldArchivesManager;
    @Resource
    private ModuleStatusChangeRecordService moduleStatusChangeRecordService;
    @Resource
    private SysProcessInfoService processInfoService;
    @Resource
    private SysMsgService msgService;
    @Resource
    private ModuleReplacePartDao moldReplacePartDao;
    @Resource
    private FaultTypeService faultTypeService;
    @Resource
    private DevMaintenThirdpartyCbDao devMaintenThirdpartyCbDao;
    @Resource
    private DeviceInfoService deviceInfoService;

    /**
     * queryList
     *
     * @param params
     * @return
     */
    @Override
    public PageUtils queryList(Map<String, Object> params) {
        //查询列表数据
        Query query = new Query(params);
        List<ModuleRepairRocordEntity> moduleRepairRocordList = moldRepairRecordService.queryList(query);
        int total = moldRepairRecordService.queryTotal(query);
        return new PageUtils(moduleRepairRocordList, total, query.getLimit(), query.getPage());
    }

    /**
     * callRepair
     *
     * @param moldRepairRecord
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean callRepair(ModuleRepairRocordEntity moldRepairRecord) {
        // 1、更新模具状态为维修
        ModuleArchivesEntity moduleArchives = moduleArchivesDao.queryObject(moldRepairRecord.getMoldId());
        cn.hutool.core.lang.Assert.notNull(moduleArchives);
        moldRepairRecord.setWorkshop(moduleArchives.getSubShop());
        moldRepairRecord.setRepairDate(DateUtil.date());
        // 模具维修没有派工流程，报修后状态默认为已派工
        moldRepairRecord.setStatus(MoldPmTicketProgressConst.DISPATCH);
        // 保存紧急维修工单
        boolean callRepairResult = moldRepairRecordService.save(moldRepairRecord) > 0;
        if (callRepairResult) {

            cn.hutool.core.lang.Assert.notNull(moduleArchives, "模具[{}]不存在，请确认！", moldRepairRecord.getMoldId());
            // 2、保存模具状态变更信息
            if (moduleStatusChangeRecordService.checkMoldStatusChangable(moduleArchives.getId(), MoldStatusChangeAction.REPAIR)) {
                moldArchivesManager.changeStatusByMoldId(moduleArchives.getId(), null, MoldStatusChangeAction.REPAIR);
            }
            // 3、保存流程信息
            sysProcessInfoService.saveProcessInfo(moldRepairRecord.getId(), ProcessInfoEnum.MDE_YJWH, 1, "", "模具紧急维修-生产组长添加成功");
        }
        return callRepairResult;
    }

    /**
     * confirmRepair
     *
     * @param moduleRepairRocord
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean confirmRepair(ModuleRepairRocordEntity moduleRepairRocord) {
        moduleRepairRocord.setStatus(MoldPmTicketProgressConst.START_REPAIR);
        moduleRepairRocord.setOrderExecuteDate(DateUtil.date());
        return moldRepairRecordService.update(moduleRepairRocord) > 0;
    }

    /**
     * addRepairRecord
     *
     * @param repairRecordParam 工单维修记录信息
     * @return
     */
    @Override
    public boolean addRepairRecord(BaseRepairRecordParamVO<ModuleRepairRocordEntity> repairRecordParam) {
        ModuleRepairRocordEntity moldRepairRocord = repairRecordParam.getTicket();
        Assert.notNull(moldRepairRocord, "模具紧急维护工单不存在！");
        CopyOptions copyOptions = CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true);
        BeanUtil.copyProperties(repairRecordParam, moldRepairRocord, copyOptions);
        moldRepairRocord.setFaultType(repairRecordParam.getType());
        return moldRepairRecordService.update(moldRepairRocord) > 0;
    }

    /**
     * completeRepair
     *
     * @param moduleRepairRocord
     * @return
     */
    @Override
    public boolean completeRepair(ModuleRepairRocordEntity moduleRepairRocord) {
        // 1、更新维修工单状态和结束维修时间
        moduleRepairRocord.setStatus(MoldPmTicketProgressConst.END_REPAIR);
        moduleRepairRocord.setOrderEndDate(DateUtil.date());
        return moldRepairRecordService.update(moduleRepairRocord) > 0;
    }

    /**
     * addDevMaintenanceException
     *
     * @param devRepairExceptionParam 设备维修过程中发现的异常信息
     * @return
     */
    @Override
    public boolean addDevMaintenanceException(DevRepairExceptionParam devRepairExceptionParam) {
        // 获取设备详情
        ModuleRepairRocordEntity moduleRepairRocord = moldRepairRecordService.queryObject(devRepairExceptionParam.getRepairTicketId());
        Assert.notNull(moduleRepairRocord, "模具紧急维护工单信息不存在，工单ID: " + devRepairExceptionParam.getRepairTicketId());
        // 获取设备详情
        ModuleArchivesEntity moduleArchives = moduleArchivesService.queryObjectByNo(moduleRepairRocord.getModuleNo());
        Assert.notNull(moduleArchives, "模具信息不存在!");
        // 保存异常记录信息
        ModuleErrorEntity excepRecord = new ModuleErrorEntity();
//        BeanUtil.copyProperties(devRepairExceptionParam, excepRecord);
//        excepRecord.setExType(ExceptionSourceType.REPAIR);
//        excepRecord.setDevId(moduleArchives.getId());
//        excepRecord.setWorkshopId(deviceInfo.getDevFarm());
//        excepRecord.setDutyUserId(devRepairExceptionParam.getPlanExecutorId());
//        excepRecord.setCreateUser(devRepairExceptionParam.getPlanExecutorId());
//        return excepRecordService.save(excepRecord) > 0;
        return true;
    }

    /**
     * doYearlyMoldFaultStat
     *
     * @param yearly   年度
     * @param moldCode 模具编码
     * @return
     */
    @Override
    public Map<Integer, MoldYearlyFaultStatDTO> doYearlyMoldFaultStat(Integer yearly, String moldCode) {
        Map<Integer, MoldYearlyFaultStatDTO> YearlyMoldFaultStat = new LinkedHashMap<>();
        List<MoldYearlyFaultStatDTO> moldYearlyFaultStatList = moduleRepairRocordDao.doYearlyMoldFaultStat(yearly, moldCode);
        if (CollectionUtil.isNotEmpty(moldYearlyFaultStatList)) {
            YearlyMoldFaultStat = moldYearlyFaultStatList.stream().collect(Collectors.toMap(MoldYearlyFaultStatDTO::getMonth, a -> a, (k1, k2) -> k1));
        }
        return YearlyMoldFaultStat;
    }

    @Override
    public ModuleRepairRocordEntity handThirdPartyCallback(DevMaintenThirdpartyCbEntity callbackData) {
        ModuleRepairRocordEntity repairTicket = null;
        Integer repairStage = callbackData.getRepairStage();
        if (DevRepairTicketStage.CALL_REPAIR.equals(repairStage)) {
            repairTicket = new ModuleRepairRocordEntity();
            DeviceInfoEntity device = deviceInfoService.queryObject(callbackData.getDevId());
            cn.hutool.core.lang.Assert.notNull(device);
            repairTicket.setWorkshop(device.getDevFarm());
            repairTicket.setDevId(device.getId());
            repairTicket.setReport(SysUserConst.HMI_USER_REAL_NAME);
            repairTicket.setFaultCode(callbackData.getFaultCode());
            repairTicket.setFaultDesc(callbackData.getFaultDesc());

            // 获取并设置ERMS系统中的模具故障类型信息
            FaultTypeEntity faultType = faultTypeService.queryOrCreateIfNotExists(2, "71", callbackData.getFaultCode(), callbackData.getFaultDesc(), "HMI一键报修检测不存在时自动添加！");
            repairTicket.setFaultType(faultType.getId());
            repairTicket.setFaultCode(faultType.getFaultCode());
            repairTicket.setFaultDesc(faultType.getTypeName());
            // 设置报修时间
            repairTicket.setRepairDate(callbackData.getUploadTime());
            // 设置模具状态
            repairTicket.setStatus(MoldPmTicketProgressConst.CALL_REPAIR);
            // 默认暂不换件
            repairTicket.setProgress(0);
            int saveNum = moldRepairRecordService.save(repairTicket);
            if (saveNum > 0) {
                // 回填ERMS维修单ID到第三方回调信息中，作为统一识别
                devMaintenThirdpartyCbDao.updateErmsBusId(callbackData.getId(), repairTicket.getId());
            }
        } else if (DevRepairTicketStage.START_REPAIR.equals(repairStage)) {
            /*
                从已关联的模具维修工单中找出关联模具维修工单
                修改状态和工单开始时间
             */
            String ermsBusId = callbackData.getErmsBusId();
            cn.hutool.core.lang.Assert.isTrue(StrUtil.isNotEmpty(ermsBusId));
            ModuleRepairRocordEntity moldRepairTicket = moldRepairRecordService.queryObject(ermsBusId);
            Assert.notNull(moldRepairTicket);
            /*
                由于已经出现了操作工误操作导致的维修开始信号，晚于维修结束信号到来的场景
                所以收到开始维修信号时不处理已结束的模具维修工单
             */
            if (NumberUtil.equals(MoldPmTicketProgressConst.END_REPAIR, moldRepairTicket.getStatus())) {
                return repairTicket;
            }
            moldRepairTicket.setStatus(MoldPmTicketProgressConst.START_REPAIR);
            // 只有ERMS工单中没有设置时间时在进行覆盖
            if (moldRepairTicket.getOrderExecuteDate() == null) {
                moldRepairTicket.setOrderExecuteDate(callbackData.getStartRepairTime());
            }
            moldRepairRecordService.update(moldRepairTicket);
        } else if (DevRepairTicketStage.END_REPAIR.equals(repairStage)) {
             /*
                从已关联的模具维修工单中找出关联模具维修工单
                修改状态和工单开始时间
             */
            String ermsBusId = callbackData.getErmsBusId();
            cn.hutool.core.lang.Assert.isTrue(StrUtil.isNotEmpty(ermsBusId));
            ModuleRepairRocordEntity moldRepairTicket = moldRepairRecordService.queryObject(ermsBusId);
            Assert.notNull(moldRepairTicket);
            moldRepairTicket.setStatus(MoldPmTicketProgressConst.END_REPAIR);
            // 只有ERMS工单中没有设置时间时在进行覆盖
            if (moldRepairTicket.getOrderEndDate() == null) {
                moldRepairTicket.setOrderEndDate(callbackData.getEndRepairTime());
            }
            moldRepairRecordService.update(moldRepairTicket);
        }
        return repairTicket;
    }

    /**
     * 更新维修记录中协助相关信息，包括协助人员、协助时间等信息
     *
     * @param ticketId       工单ID
     * @param assistPersonId 协助人员ID
     * @param nextHandleNode 下一处理节点
     */
    private void updateAssistInfo(String ticketId, String assistPersonId, int nextHandleNode) {
        DevMaintenRepairEntity repairRecord = devMaintenRepairDao.queryByTicketId(ticketId);
        if (repairRecord != null) {
            repairRecord.setOrderNo(nextHandleNode);
            if (nextHandleNode == 3) {
                repairRecord.setLevel3AssistUser(assistPersonId);
                repairRecord.setLevel3AssistStartTime(DateUtil.date());
            } else if (nextHandleNode == 2) {
                repairRecord.setLevel2AssistUser(assistPersonId);
                repairRecord.setLevel2AssistStartTime(DateUtil.date());
            }
            devMaintenRepairService.update(repairRecord);
        }
    }

    /**
     * commitApprove
     *
     * @param moduleRepairRocord 模具维修工单
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean commitApprove(ModuleRepairRocordEntity moduleRepairRocord) {
        moduleRepairRocord.setProgress(MoldReplacePartProgress.DEPT_APPROVING);
        boolean flag = moduleRepairRocordDao.update(moduleRepairRocord) > 0;
        if (flag) {
            String moduleRepairRocordId = moduleRepairRocord.getId();
            // 更新关联的换件记录状态为部门审核中
            moldReplacePartDao.updateProgress(moduleRepairRocord.getRepairCode(), MoldReplacePartProgress.DEPT_APPROVING);
            // 保存流程信息
            processInfoService.saveProcessInfo(moduleRepairRocordId, ProcessInfoEnum.MOLD_REPAIR_RP, 0, null);
            // 添加备件审批事项
            msgService.addMoldRepairApproveItem(moduleRepairRocordId, 0);
        }
        return flag;
    }

    /**
     * handleWorkshopApprove
     *
     * @param approveItemId 审批事项ID
     * @param approveStatus 审批状态
     * @param remark        审批备注
     * @return
     */
    @Override
    public HandleApproveResult handleWorkshopApprove(String approveItemId, Integer approveStatus, String remark) {
        HandleApproveResult handleApproveResult = new HandleApproveResult();
        ModuleRepairRocordEntity modlRepairRecord = moldRepairRecordService.queryObject(approveItemId);
        org.springframework.util.Assert.notNull(modlRepairRecord, "模具维修工单不存在，请确认！");
        // 校验规程进度
        org.springframework.util.Assert.isTrue(MoldReplacePartProgress.DEPT_APPROVING.equals(modlRepairRecord.getProgress()), "只可以审核处于[部门审核]状态的模具维修工单！");
        handleApproveResult.setProcessProgressStatus(ProcessProgressStatus.ING);
        handleApproveResult.setTitle(StrUtil.format("模具维修工单[{}]换件审核", modlRepairRecord.getRepairCode()));
        // 如果审核通过，则更新进度
        if (approveStatus == SysApproveStatusConst.PASSED) {
            handleApproveResult.setProcessProgressStatus(ProcessProgressStatus.END);
            modlRepairRecord.setProgress(MoldReplacePartProgress.PASSED);
        } else if (approveStatus == SysApproveStatusConst.NOT_PASSED) {
            handleApproveResult.setProcessProgressStatus(ProcessProgressStatus.ING);
            modlRepairRecord.setProgress(MoldReplacePartProgress.NOT_PASSED);
        }
        int rows = moldRepairRecordService.update(modlRepairRecord);
        if (rows > 0) {
            // 更新对应的换件记录状态
            moldReplacePartDao.updateProgress(modlRepairRecord.getRepairCode(), MoldReplacePartProgress.PASSED);
            // 设置处理人
            handleApproveResult.setUserId(modlRepairRecord.getOrderExecuteUser());
        }
        return handleApproveResult;
    }

}
